﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Compresor2
{
    public class Entropia
    {
        public int[] calcular_FA(string ff) //calcula las frcuencias de los simbolos y las devuelve en un arreglo
        {
            char[] Simbolos = new char[ff.Length];
            int[] aux = new int[ff.Length];// en este arreglo se cargan las frecuencias, se declara del tamaño del archivo completo porq no se sabe de antemano la cantidad de simbolos distintos
            Simbolos[0] = ff[0];
            aux[0] = 1;
            int q = 1;

            for (int i = 1; i < (ff.Length); i++)//recorre todos los caracteres del archivo y aumenta la frecuncia del caracter q corresponde en cada pasada
            {
                int j = 0;
                while ((j < q) && (ff[i] != Simbolos[j]))
                {
                    j++;
                }
                if (j == q)
                {
                    Simbolos[q] = ff[i];
                    aux[q] = 1;
                    q++;
                }
                else
                    aux[j]++;
            }

            int[] FA = new int[q];// como a esta altura ya se sabe la cantidad de simbolos distintos, se declara un arreglo de ese tamaño y ese es el que se retorna
            for (int i = 0; i < q; i++)
                FA[i] = aux[i];

            return FA;
        }

        public double[] calcularI(int[] FA, string ff) //calcula la I de cada simbolo
        {
            int tam = ff.Length;
            double[] I = new double[FA.Length];
            int j = 0;
            foreach (var x in FA) // recorre cada elemento de FA (todas las frecuencias absolutas)
            {
                I[j] = Math.Log(tam / x, 2);
                j++;
            }
            return I;
        }

        public double calcularH(int[] FA, double[] I, string ff) //calcula la entropia, tomando como entrada las frecuencias absolutas, la I de cada simbolo y el archivo leido
        {
            int tam = ff.Length;
            double suma = 0;
            for (int i = 0; i < FA.Length; i++)
            {
                suma += (FA[i]) * I[i];
            }
            return suma / (double)tam;// esto es porq en la sumatoria no intervinieron las frecuencias relativas, sino las absolutas
        }

        public double calcularR(double H) //calcula la redundancia
        {
            double Hmax = 8; //pues log q = 8, considerando q = 256 por tratarse de un archivo decodificado como ascii
            return (Hmax - H) / Hmax;
        }

        public Entropia(byte[] flujo)
        {
            string cadena = Encoding.ASCII.GetString(flujo); //Se decodifica como ASCII

            int[] FA = calcular_FA(cadena);
            double[] I = calcularI(FA, cadena);
            double H = calcularH(FA, I, cadena);
            Console.WriteLine("Entropía del archivo: " + H);
            double Redundancia = calcularR(H);
            Console.WriteLine("Redundancia del archivo: " + Redundancia);
        }
    }
}
